var widget = widget || { };
/**
 * Это класс виджета диалогового окна.
 * Copyright 2012, Alexander Dashkovsky
 * License: http://www.opensource.org/licenses/mit-license.php
 * @lends widget.Dialog
 */
widget.Dialog = Base.extend({
	
	id : undefined,			// идентификатор объекта
	
	items : [],				// масив элементов в поле окна

	visible : true,			// признак того, что контейнер будет отображаться
	
	/** @const */
	WIDGET_CLASS : 'wg_dialog',

	/**
	 * Конструктор класса
	 * @augments Base
	 * @class Класс виджета диалогового окна.
	 * Диалоговое окно является контейнером и поэтому может включать
	 * в себя дочерние виджеты.
	 * <div><b>Используется:</b><br/>
	 * jQuery UI плагин Dialog.</div>
	 *
	 * <p><b>CSS класс для DOM элемента - <code>wg_dialog</code></b></p>
	 * 
	 * <p><b>Параметры объекта конфигурации:</b></p>
	 * {String} <b>id</b> - Идентификатор компонента.</br>
	 * {String} <b>cls</b> - Имя класса css (или нескольких классов через пробел)
	 * которые будут добавлены компоненту.</br>
	 * {Int} <b>width</b> - Ширина компонента.</br>
	 * {Int} <b>height</b> - Высота компонента.</br>
	 * {Object[]} <b>tabs</b> - Массив секций диалогово окна.</br>
	 * {Boolean} <b>collapsible</b> - Если задано <code>true</code>, то при клике
	 * на заголовке уже открытой секции, она закроется. Таким образом можно
	 * переводить все секции в закрытое состояние.</br>
	 * {Boolean} <b>animated</b> - Признак, нужна ли анимация секций. 
	 * Если не задано, анимация по умолчанию проводится.</br>
	 * {ElementDOM} <b>renderTo</b> - Элемент DOM, в который будет прорисован диалоговое окна.</br>
	 * {Object[]} <b>listeners</b> - Массив слушателей событий.</br>
	 * 
	 * <p><b>События:</b></p>
	 * <div><b>afterrender</b> - Вызывается сразу после прорисовки диалогово окна.</div>
	 * <div class="shift1">callbackFunction(<b>component</b>, <b>domElement</b>), где:</div>
	 * <div class="shift2"><b>component</b> - компонент диалогово окна</div>
	 * <div class="shift2"><b>domElement</b> - DOM элемент диалогово окна</div>
	 * <div><b>click</b> - Вызывается при клике на область диалогово окна.</div>
	 * <div class="shift1">callbackFunction(<b>component</b>, <b>domElement</b>), где:</div>
	 * <div class="shift2"><b>component</b> - компонент диалогово окна</div>
	 * <div class="shift2"><b>domElement</b> - DOM элемент диалогово окна</div>
	 * <div><b>change</b> - Вызывается при смене секции диалогово окна.</div>
	 * <div class="shift1">callbackFunction(<b>component</b>, <b>index</b>, <b>section</b>, <b>domElement</b>), где:</div>
	 * <div class="shift2"><b>component</b> - компонент диалогово окна</div>
	 * <div class="shift2"><b>index</b> - индекс выбранной секции</div>
	 * <div class="shift2"><b>section</b> - компонент выбранной секции</div>
	 * <div class="shift2"><b>domElement</b> - DOM элемент диалогово окна</div>
	 * <div><b>hide</b> - Вызывается когда аккордион был спрятан.</div>
	 * <div class="shift1">callbackFunction(<b>component</b>, <b>domElement</b>), где:</div>
	 * <div class="shift2"><b>component</b> - компонент диалогово окна</div>
	 * <div class="shift2"><b>domElement</b> - DOM элемент диалогово окна</div>
	 * <div><b>show</b> - Вызывается когда аккордион был показан.</div>
	 * <div class="shift1">callbackFunction(<b>component</b>, <b>domElement</b>), где:</div>
	 * <div class="shift2"><b>component</b> - компонент диалогово окна</div>
	 * <div class="shift2"><b>domElement</b> - DOM элемент диалогово окна</div>
	 * 
	 * <p><b>Пример:</b></p>
	 * <pre class="code">
	 * var dialog1 = new widget.Dialog({
	 * 	title : 'Модальное окно',
	 * 	html : 'Большой привет всем!',
	 * 	modal : true,
	 * 	height: 240,
	 * 	width : 400,
	 * 	buttons: [
	 * 		{
	 * 			text: "Ok",
	 * 			click: function() { dialog1.close(); }
	 * 		}
	 * 	]
	 * });
	 * </pre>
	 * 
	 * @constructs
	 * @param {Object} config Конфигурационный объект компонента.
	 */
	constructor : function(config) {
		this.contentContainer = null;
		this.config = config || {} ;
		this.id = (config.id)? config.id : this.WIDGET_CLASS+this.generateId();
		this.config.id = this.id;
		if (this.config.items) {
			this.contentContainer = new widget.Container({
				id : (this.getId()+'_content'),
				items : this.config.items 
			});
		}
	},
	
	/**
	 * Эта функция возвращает идентификатор диалогово окна.
     * @public 
	 * @function
     * @memberOf widget.Dialog#
	 * @return {string} - идентификатор контейнера
	 */
	getId : function() {
		return this.id;
	},
	
	/**
	 * Эта функция возвращает тип объекта
     * @public 
	 * @function
     * @memberOf widget.Dialog#
	 * @return {string} - тип объекта
	 */
	getType : function() {
		return this.type;
	},
	
	/**
	 * Возвращает признак видимости диалогово окна.
     * @public 
	 * @function
     * @memberOf widget.Dialog#
	 * @return {boolean} - true, если объект должен быть показан. Иначе false.
	 */
	isVisible : function() {
		return this.visible;
	},
	
	/**
	 * Установить признак видимости диалогово окна.
     * @public 
	 * @function
     * @memberOf widget.Dialog#
	 * @param {boolean} visible признак доступности объекта.
	 * @return none
	 */
	setVisible : function(visible) {
		this.visible = visible;
	},
	
    /**
     * @private 
	 * @function
     * This function generate unique id using date-time, math round operation, reverse string
     * by length=10 chars
     * @return {string} id
    */
    generateId : function() {    
        return Math.round(((new Date()).getTime()+Math.random())*100).toString().split('').reverse().join('').substr(0,10);
    },

	/**
	 * Выполняется отрисовка диалогово окна.
     * @private 
	 * @function
	 * @param (elementDOM) renderTo Элемент DOM, внутри которого будет создан аккордион.
	 * @return none
	 */
	render : function() {
		if (this.element) {
			this.element.remove();
		}

		var me = this;
		var renderTo = $('body');

		var tpl = '<div class="'+this.WIDGET_CLASS+'" id="' + this.getId() + '"';
		if (this.config.title) {
			tpl += ' title="' + this.config.title + '"';
		}
		tpl += '></div>';
		
		this.element = $(tpl);
		
		if (this.config.cls) {
			this.applyClassToElement(this.config.cls, this.element)
		}
		if (renderTo) {
			$(this.element).appendTo(renderTo);

			if (this.config.html) {
				$(this.element).append(this.config.html);
			} else if (this.config.items) {
				this.contentContainer.render(this.element);
			}

			var opts = {};
			if (this.config.width) {
				opts.width = this.config.width;
			}
			if (this.config.height) {
				opts.height = this.config.height;
			}
			if (this.config.buttons) {
				opts.buttons = this.config.buttons;
			}
			if (this.config.modal) {
				opts.modal = this.config.modal;
			}
			opts.close = function(event, ui) {
				$(this).remove();
			};
			opts.create = function(event, ui) {
				$(event.target).parent().css('position', 'fixed');
			};
			this.element.dialog(opts);

		}
	},
	
	/**
	 * Закрыть окно диалога. 
     * @public 
	 * @function
     * @memberOf widget.Dialog#
	 */
	close : function() {
		this.element.dialog('close');
	},
	
	
	/**
	 * Спрятать контейнер 
     * @public 
	 * @function
     * @memberOf widget.Dialog#
	 */
	hide : function() {
		var oldVisible = this.visible; 
		this.visible = false;
		if (this.visible != oldVisible) {
			this.element.addClass("hidden");
			this.onHide();
		}
	},
	
	/**
	 * Показать контейнер 
     * @public 
	 * @function
     * @memberOf widget.Dialog#
	 */
	show : function() {
		var oldVisible = this.visible; 
		this.visible = true;
		if (this.visible != oldVisible) {
			this.element.removeClass("hidden");
			this.onShow();
		}
	},
	
	/**
	 * Удалить контейнер 
     * @public 
	 * @function
     * @memberOf widget.Dialog#
	 */
	remove : function() {
		this.element.remove();
		this.onRemove();
	},
	
	/**
	 * Функция отрабатывает после того, как элемент будет показан. 
     * @private 
	 * @function
	 */
	onShow : function() {
		if (this.config.listeners && this.config.listeners.show) {
			this.config.listeners.show(this, this.element);
		}
	},
	
	/**
	 * Функция отрабатывает после того, как элемент будет удален. 
     * @private 
	 * @function
	 */
	onRemove : function() {
		if (this.config.listeners && this.config.listeners.remove) {
			this.config.listeners.remove(this, this.element);
		}
	},
	
	/**
	 * Эта функция возвращает указатель на контейнер содержимого диалогового окна.
     * @public 
	 * @function
     * @memberOf widget.Dialog#
	 * @return {widget.Container} - контейнер содержимого диалогового окна.
	 */
	getContentContainer : function() {
		return this.contentContainer;
	},
	
	/**
	 * Функция добавляет класс(классы) к элементу.
     * @function
     * @private 
	 */
	applyClassToElement : function(cls, element) {
		if (cls) {
			var arr = cls.split(' ');
			for (var i=0; i<arr.length; i++) {
				$(element).addClass(arr[i]);
			}
		}
	},
	
	/**
     * @public 
	 * @function
     * @memberOf widget.Dialog#
	 */
	toString : function() {
		return 'widget.Dialog:{"'+this.getType()+'":{"id":"'+this.getId()+'"}}'
	}

});
